﻿/////////////////////////////////////////////////////////////////////////////////////////////
// <copyright file="Extensions.cs" company="Microsoft Corporation">
//     Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
/////////////////////////////////////////////////////////////////////////////////////////////

namespace Microsoft.LiveAtEdu.Samples.Powershell
{
    using System;
    using System.Collections.ObjectModel;
    using System.Management.Automation;
    using System.Management.Automation.Runspaces;
    using System.Security;

    /// <summary>
    /// Utility methods implemented as extensions.
    /// </summary>
    public static class Extensions
    {
        /// <summary>
        /// Script to set variable
        /// </summary>
        private const string SetVariableScript = "Set-Variable";

        /// <summary>
        /// Helper method to convert String to SecureString.
        /// </summary>
        /// <param name="str">String to be converted.</param>
        /// <returns>Secure string representation.</returns>
        public static SecureString ToSecureString(this string str)
        {
            var secureData = new SecureString();

            if (!string.IsNullOrEmpty(str))
            {
                for (int i = 0; i < str.Length; i++)
                {
                    secureData.AppendChar(str[i]);
                }
            }

            return secureData;
        }

        /// <summary>
        /// Execute a powershell command.
        /// </summary>
        /// <param name="runspace">Runspace to run the command.</param>
        /// <param name="command">Powershell command.</param>
        /// <returns>Result collection.</returns>
        public static Collection<PSObject> ExecuteCommand(this Runspace runspace, PSCommand command)
        {
            return ExecuteCommand<PSObject>(runspace, command);
        }

        /// <summary>
        /// Execute a powershell command.
        /// </summary>
        /// <typeparam name="T">Type of command execution result.</typeparam>
        /// <param name="runspace">Runspace to run the command.</param>
        /// <param name="command">Powershell command.</param>
        /// <returns>Result collection.</returns>
        public static Collection<T> ExecuteCommand<T>(this Runspace runspace, PSCommand command)
        {
            if (command == null)
            {
                throw new ArgumentOutOfRangeException("command");
            }

            if (runspace == null)
            {
                throw new ArgumentOutOfRangeException("runspace");
            }

            using (var ps = PowerShell.Create())
            {
                ps.Commands = command;
                ps.Runspace = runspace;

                return ps.Invoke<T>();
            }
        }

        /// <summary>
        /// Method to create PS credential and set it as PS environment variable.
        /// </summary>
        /// <param name="runspace">Runspace to run the command.</param>
        /// <param name="userName">The user name.</param>
        /// <param name="password">The user password.</param>
        public static void SetCredential(this Runspace runspace, string userName, SecureString password)
        {
            if (runspace == null)
            {
                throw new ArgumentOutOfRangeException("runspace");
            }

            if (string.IsNullOrEmpty(userName))
            {
                throw new ArgumentOutOfRangeException("userName");
            }

            if (password == null)
            {
                throw new ArgumentOutOfRangeException("password");
            }

            var cred = new PSCredential(userName, password);
            SetVariable(runspace, Constants.Credential, cred);
        }

        /// <summary>
        /// Method to set passed in object to PS environment variable
        /// </summary>
        /// <param name="runspace">Runspace to run the command.</param>
        /// <param name="name">name of the variable</param>
        /// <param name="value">value of the variable</param>
        public static void SetVariable(this Runspace runspace, string name, object value)
        {
            if (runspace == null)
            {
                throw new ArgumentOutOfRangeException("runspace");
            }

            if (string.IsNullOrEmpty(name))
            {
                throw new ArgumentOutOfRangeException("name");
            }

            if (value == null)
            {
                throw new ArgumentOutOfRangeException("value");
            }

            var command = new PSCommand();
            command.AddCommand(SetVariableScript);
            command.AddParameter(Constants.Name, name);
            command.AddParameter(Constants.Value, value);
            runspace.ExecuteCommand<PSObject>(command);
        }
    }
}
